package org.aspectsense.middleware.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JPanel;
import javax.swing.JScrollPane;

import org.aspectsense.middleware.adaptation.AdaptationGraph;
import org.aspectsense.middleware.adaptation.BigraphComponentNode;
import org.aspectsense.middleware.adaptation.BigraphServiceNode;

public class DrawOverviewGraph extends JPanel 
{
	private Hashtable <String, Point> serviceNodesCoordinates;
	private Hashtable <String, Point> componentNodesCoordinates;
	
	DrawOverviewGraph()
	{
		super();
		serviceNodesCoordinates = new Hashtable <String, Point>();
		componentNodesCoordinates = new Hashtable <String, Point>();
		
	}
	
	
	
	
	
	public void paintComponent(Graphics g) 
	{
        super.paintComponent(g);   
       int X = 5, Y = 10, ar_width=20, ar_height=20, ar_angle=60, startAngle=0, nameLength=20;
       double lengthX=0.0, lengthY=0.0, lineLength=0.0;   
       int d=10;
       Dimension size = getSize();
       int panelWidth = size.width;
      double space;
      
      
        LinkedList<BigraphComponentNode> components = AdaptationGraph.getComponents ();
        HashMap<String, BigraphServiceNode> services = AdaptationGraph.getServices ();
        Collection<BigraphServiceNode> serviceNodes = services.values();
        Iterator <BigraphServiceNode> snodeItr = serviceNodes.iterator();
        Iterator <BigraphComponentNode> cnodeItr = components.iterator();
        BigraphServiceNode bsn;
        BigraphComponentNode bcn;
        Point startPoint, endPoint;
              
        //Draw Nodes
        
        if (services!=null && services.size()>0)
        {
        	//space = panelWidth /services.size();
	        space = 140;
        	while (snodeItr.hasNext())
	        {
	        	bsn = snodeItr.next();
	        	if (bsn.isEndUser())
	        		g.setColor(Color.red);
	        	else
	        		g.setColor(Color.green);
	        	g.fillOval(X, Y, d, d);
	            g.drawOval(X, Y, d, d);
	            g.setColor(Color.black);
	            g.drawString(bsn.getShortServiceName(), X, Y);
	            bsn.setCoordinates(new Point (X,Y));
	            X += space;
	        }
        }
        
       
        if (components!=null && components.size()>0)
        {
        	X = 5;
        	Y = (int) (size.getHeight()-10);
        	//space = panelWidth /components.size();
        	space = 130;
	        while (cnodeItr.hasNext())
	        {
	        	bcn = cnodeItr.next();
	        	g.setColor(Color.black);
	        	g.fillOval(X, Y, d, d);
	            g.drawOval(X, Y, d, d);
	            g.drawString(bcn.getShortComponentName(), X, Y);
	            bcn.setCoordinates(new Point (X,Y));
	            X += space;
	        }
        }
        //ENDOF Draw Nodes
        
        //Draw Lines from components to services
        Graphics2D g2 = (Graphics2D) g;
       
        if (components!=null && components.size()>0)
        {
        	 cnodeItr = components.iterator();
             LinkedList <BigraphServiceNode> connections;
             Iterator  <BigraphServiceNode> coneItr;
	        while (cnodeItr.hasNext())
	        {
	        	bcn = cnodeItr.next();
	        	startPoint = bcn.getCoordinates();
	        	assert(startPoint!=null);
	        	connections = bcn.getConnections ();
	  
	        	coneItr = connections.iterator();
	        	while (coneItr.hasNext())
	        	{
	        		bsn = coneItr.next();
	        		endPoint = bsn.getCoordinates();
	        		g2.setColor(Color.blue);
	        		g2.draw(new Line2D.Double(startPoint.getX(), startPoint.getY()+5.00, endPoint.getX(), endPoint.getY()+5.00));
	        		
	        		// Calulate the length of the line
	        		lengthX = endPoint.getX() - startPoint.getX();
	        		lengthY = endPoint.getY() - startPoint.getY();
	        		lineLength = Math.sqrt (lengthX*lengthX + lengthY*lengthY);

	        		startAngle = (int)Math.toDegrees(Math.asin(lengthY/lineLength));
	        		if (lengthX > 0)
	        			startAngle = (180 - startAngle - 30);
	        		else
	        			startAngle = (startAngle - 30);

	        		// Draw the arrow head
	        		g.fillArc ( ((int) (endPoint.getX() - (ar_width/2))), ((int)(endPoint.getY()+5 - (ar_height/2)+1)) ,ar_width, ar_height,startAngle,ar_angle);
	        		
	        	}
	        }
        }
        //Draw Lines from services to Components
        
        if (services!=null && services.size()>0)
        {
        	snodeItr = services.values().iterator();
        	HashSet<BigraphComponentNode> connections2;
        	Iterator  <BigraphComponentNode> cone2Itr;
        	while (snodeItr.hasNext())
	        {
	        	bsn = snodeItr.next();
	        	startPoint = bsn.getCoordinates();
	        	assert(startPoint!=null);
	        	connections2 = bsn.getConnections ();
	        	cone2Itr = connections2.iterator();
	        	while (cone2Itr.hasNext())
	        	{
	        		bcn = cone2Itr.next();
	        		endPoint = bcn.getCoordinates();
	        		g2.setColor(Color.white);
	        		g2.draw(new Line2D.Double(startPoint.getX(), startPoint.getY()+5.00, endPoint.getX(), endPoint.getY()-5.00));
	        		
	        		// Calulate the length of the line
	        		lengthX = endPoint.getX() - startPoint.getX();
	        		lengthY = endPoint.getY() - startPoint.getY();
	        		lineLength = Math.sqrt (lengthX*lengthX + lengthY*lengthY);

	        		startAngle = (int)Math.toDegrees(Math.asin(lengthY/lineLength));
	        		if (lengthX > 0)
	        			startAngle = (180 - startAngle - 30);
	        		else
	        			startAngle = (startAngle - 30);

	        		// Draw the arrow head
	        		g.fillArc ( ((int) (endPoint.getX() - (ar_width/2))), ((int)(endPoint.getY() - (ar_height/2)+1)) ,ar_width, ar_height,startAngle,ar_angle);
	        		
	        	}
	        }
        }
        
     }
	
	public void drawMaxPaths ()
	{
		Point start, end;
		LinkedList <BigraphComponentNode> maxComponents = AdaptationGraph.maxComponents;
		System.out.println ("HI");
		for (BigraphComponentNode node:maxComponents)
		{
			if (node==null)
			{
				System.out.println ("maxComponents contains a null node!");
			}
			start = node.getCoordinates();
			for (BigraphServiceNode sn:node.getConnections())
			{
				end = sn.getCoordinates();
				Graphics2D g2 = (Graphics2D) this.getGraphics();
				g2.setColor(Color.red);
				g2.draw(new Line2D.Double(start.getX(), start.getY()+5.00, end.getX(), end.getY()+5.00));
			}
		}
	}

}
